package com.bom.core.util.temp;

import cn.hutool.core.util.ReflectUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.UtilityClass;
import org.codehaus.commons.compiler.CompileException;
import org.codehaus.janino.ExpressionEvaluator;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.stream.Stream;

@UtilityClass
public class Temps {
    /**
     * 全局的一个表达式引擎
     */
    private ExpressionEvaluator evaluator = new ExpressionEvaluator();

    /**
     * p is a obj
     */
    public synchronized <P> Object expr(String exprStr, P param) throws CompileException, InvocationTargetException {
        try {
            Field[] fields = ReflectUtil.getFieldsDirectly(param.getClass(), true);
            String[] strings = Arrays.stream(fields).map(Field::getName).toArray(value -> new String[fields.length]);
            Class<?>[] classes = Arrays.stream(fields).map(Field::getType).toArray(value -> new Class<?>[fields.length]);
            evaluator.setParameters(strings, classes);
            evaluator.cook(exprStr);
            return evaluator.evaluate(Stream.of(fields).map(f -> ReflectUtil.getFieldValue(param, f)).toArray(value -> new Object[fields.length]));
        } finally {
            evaluator = new ExpressionEvaluator();
        }
    }

    public static void main(String[] args) throws CompileException, InvocationTargetException {
        Object expr = Temps.expr("import cn.hutool.core.util.StrUtil;" +
                "StrUtil.isBlank(b)", new A(12, "19"));
        System.out.println(expr);
    }

    @Data
    @AllArgsConstructor
    public static class A {
        private Integer a;
        private String b;
    }
}
